package health_system.health_system.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;

@Getter
@Setter
@Entity
@Table(name = "chat_messages")
public class ChatMessage extends BaseEntity {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "chat_room_id", nullable = false)
    private ChatRoom chatRoom;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "sender_id", nullable = false)
    private User sender;
    
    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private MessageType messageType;
    
    @Size(max = 2000)
    @Column(columnDefinition = "TEXT")
    private String textContent;
    
    @Size(max = 255)
    private String mediaUrl;
    
    private Integer mediaDuration; // for audio/video in seconds
    
    @OneToMany(mappedBy = "message", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<MessageReadStatus> readStatuses = new HashSet<>();
    
    @Column(nullable = false)
    private Boolean isDeliveredToServer = false;
    
    private LocalDateTime deliveredAt;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "reply_to_message_id")
    private ChatMessage replyToMessage;
    
    @Column(nullable = false)
    private Boolean isRecalled = false;
    
    private LocalDateTime recalledAt;
    
    @Column(nullable = false)
    private Boolean isPinned = false;
    
    private LocalDateTime pinnedAt;
    
    public enum MessageType {
        TEXT, IMAGE, VIDEO, AUDIO, FILE, LOCATION, CONTACT, SCREEN_SHARE
    }

    public ChatRoom getChatRoom() {
        return chatRoom;
    }

    public void setChatRoom(ChatRoom chatRoom) {
        this.chatRoom = chatRoom;
    }

    public User getSender() {
        return sender;
    }

    public void setSender(User sender) {
        this.sender = sender;
    }

    public MessageType getMessageType() {
        return messageType;
    }

    public void setMessageType(MessageType messageType) {
        this.messageType = messageType;
    }

    public String getTextContent() {
        return textContent;
    }

    public void setTextContent(String textContent) {
        this.textContent = textContent;
    }

    public String getMediaUrl() {
        return mediaUrl;
    }

    public void setMediaUrl(String mediaUrl) {
        this.mediaUrl = mediaUrl;
    }

    public Integer getMediaDuration() {
        return mediaDuration;
    }

    public void setMediaDuration(Integer mediaDuration) {
        this.mediaDuration = mediaDuration;
    }

    public Set<MessageReadStatus> getReadStatuses() {
        return readStatuses;
    }

    public void setReadStatuses(Set<MessageReadStatus> readStatuses) {
        this.readStatuses = readStatuses;
    }

    public Boolean getDeliveredToServer() {
        return isDeliveredToServer;
    }

    public void setDeliveredToServer(Boolean deliveredToServer) {
        isDeliveredToServer = deliveredToServer;
    }

    public LocalDateTime getDeliveredAt() {
        return deliveredAt;
    }

    public void setDeliveredAt(LocalDateTime deliveredAt) {
        this.deliveredAt = deliveredAt;
    }

    public ChatMessage getReplyToMessage() {
        return replyToMessage;
    }

    public void setReplyToMessage(ChatMessage replyToMessage) {
        this.replyToMessage = replyToMessage;
    }

    public Boolean getRecalled() {
        return isRecalled;
    }

    public void setRecalled(Boolean recalled) {
        isRecalled = recalled;
    }

    public LocalDateTime getRecalledAt() {
        return recalledAt;
    }

    public void setRecalledAt(LocalDateTime recalledAt) {
        this.recalledAt = recalledAt;
    }

    public Boolean getPinned() {
        return isPinned;
    }

    public void setPinned(Boolean pinned) {
        isPinned = pinned;
    }

    public LocalDateTime getPinnedAt() {
        return pinnedAt;
    }

    public void setPinnedAt(LocalDateTime pinnedAt) {
        this.pinnedAt = pinnedAt;
    }
}